#include "sct/rtspserver/streamsource.h"

namespace sct
{

CStreamSource::CStreamSource(CServerInterface * server):
		mMutex(NULL),
		mDelay(300000),
		mServer(server),
		mName(sct::toString("CStreamSource %p", this))
{
	mMutex = new CMutex;
}

void CStreamSource::setName(const std::string & name)
{
	mName = name;
}


CStreamSource::~CStreamSource()
{
	while(1)
	{
		if(mBuffer.empty())
		{
			break;
		}

		CBufferItem* item = mBuffer.front();
		mBuffer.pop_front();

		CBufferItem::free(item);
	}

	SCT_DELETE(mMutex);
}

bool CStreamSource::hasdata()
{
	CAutoLock locker(mMutex);

	return !mBuffer.empty();
}

int CStreamSource::getdata(void*p, const int len, int64_t*pts, int*ntrunc, const int force)
{
	CAutoLock locker(mMutex);

	//FIXME:adjust a bug in live555
	if((!force) && (mServer->needStopStream()) )
	{
		SCT_LOGD("[%s] stop stream cause by server!", mName.c_str());
		return 0;
	}

	if(mBuffer.empty())
	{
		return -1;
	}

	CBufferItem* item = mBuffer.front();
	mBuffer.pop_front();

	int ret = item->len;
	if(len < ret)
	{
		ret = len;
		SCT_LOGD("trunc data!");
	}

	if(ntrunc)
	{
		*ntrunc = item->len - ret;
	}

	if(pts)
	{
		*pts = item->pts;
	}

	if(p)
	{
		memcpy(p, item->data, ret);
	}

	CBufferItem::free(item);

	return ret;
}


void CStreamSource::putdata(const void*p, const int len, const int64_t pts)
{
	CAutoLock locker(mMutex);

	onPutData(p, len, pts);
}

void CStreamSource::onPutData(const void*p, const int len, const int64_t pts)
{
	if(!mBuffer.empty())
	{
		int64_t n = 1;
		n <<=32;

		int64_t diff = mBuffer.back()->pts;
		diff = diff - mBuffer.front()->pts;
		diff += n;
		diff %= n;

		if(diff > mDelay)
		{
			CBufferItem::free(mBuffer.front());
			mBuffer.pop_front();

			if(!mServer->needStopStream())
			{
				//SCT_LOG("[%s] put data lost!!!:%lld",  mName.c_str(), diff);
			}
		}
	}

	CBufferItem* item = new CBufferItem;
	item->data = new uint8_t[len];
	memcpy(item->data, p, len);

	item->len = len;

	item->pts = mServer->getPTS(pts);

	mBuffer.push_back(item);
}


void CStreamSource::setMaxDelay(const int d)
{
	CAutoLock locker(mMutex);
	mDelay = d;
}


}//end namespace
